/********************************************
 * 功能说明: 
 * 模块名称: 
 * 系统名称: 
 * 软件版权: 
 * 系统版本: 1.0.0
 * 开发人员: zhangfb
 * 开发时间: 2019/6/3 23:02
 * 审核人员: 
 * 相关文档: 
 * 修改记录: 修改日期 修改人员 修改说明
 *********************************************/
package com.hyacinth.aurora.ioc;

import com.hyacinth.aurora.core.ClassHelper;
import com.hyacinth.aurora.core.bean.BeanManager;
import com.hyacinth.aurora.core.exception.InitializationError;
import com.hyacinth.aurora.core.exception.SingleClassInstanceException;
import com.hyacinth.aurora.core.init.Initialization;
import com.hyacinth.aurora.ioc.annotation.Inject;
import com.hyacinth.aurora.ioc.annotation.Service;
import com.hyacinth.aurora.utils.ArrayUtil;
import com.hyacinth.aurora.utils.CollectionUtil;
import com.hyacinth.aurora.utils.MapUtil;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

/**
 * @author zhangfb
 * @version 1.0.0.1
 * @since JDK 1.8
 */
public class IocHelper extends Initialization {

    private IocHelper() throws SingleClassInstanceException {
        super();
    }

    @Override
    protected void doInit() throws Exception {
        // 获取并遍历所有的 Bean 类
        Map<String, Object> beanMap = BeanManager.getInstance(BeanManager.class).getBeanMap();
        if (MapUtil.isNotEmpty(beanMap)) {
            beanMap.forEach((beanName, beanInstance) -> {
                // 获取Bean类中所有的字段（不包括父类中的方法）
                Field[] fields = beanInstance.getClass().getDeclaredFields();
                if (ArrayUtil.isNotEmpty(fields)) {
                    // 遍历所有的 Bean 字段
                    for (Field beanField : fields) {
                        // 判断当前 Bean 字段是否带有 Inject 注解
                        if (beanField.isAnnotationPresent(Inject.class)) {
                            // 获取 Bean 字段对应的接口
                            Class<?> interfaceClass = beanField.getType();
                            // 获取 Bean 字段对应的实现类
                            Class<?> implementClass = findImplementClass(interfaceClass);
                            if (implementClass == null) {
                                throw new InitializationError("依赖注入失败！，接口【{}】无具体实现类", interfaceClass.getSimpleName());
                            }
                            // 若存在实现类，则执行以下代码
                            Object implementInstance = beanMap.get(implementClass.getSimpleName());
                            if (implementInstance == null) {
                                throw new InitializationError("依赖注入失败！，beanMap中无此接口【{}】的实现实例", interfaceClass.getSimpleName());
                            }
                            // 设置该 Bean 字段的值
                            beanField.setAccessible(true); // 将字段设置为 public
                            try {
                                beanField.set(beanInstance, implementInstance); // 设置字段初始值
                            } catch (IllegalAccessException e) {
                                throw new InitializationError("注入属性值失败，beanName={}，implementInstanceName={}", beanName, interfaceClass.getSimpleName());
                            }
                        }
                    }
                }
            });
        }
    }

    @Override
    protected void doDestroy() throws Exception {

    }

    /**
     * 查找实现类
     */
    public static Class<?> findImplementClass(Class<?> interfaceClass) {
        Class<?> implClass = null;
        // TODO 待优化，增加加载策略，指定实现类名称
        // 获取该接口所有的实现类
        List<Class<?>> implementClassList = ClassHelper.getClassListBySuper(interfaceClass);
        if (CollectionUtil.isNotEmpty(implementClassList)) {
            // 获取第一个实现类
            implClass = implementClassList.get(0);
        }
        // 返回实现类对象
        return implClass;
    }
}
